/**
 * 
 */
package org.t2.game.server.module.player.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;

import org.gaming.ruler.lifecycle.Lifecycle;
import org.gaming.ruler.schedule.LoopingTask;
import org.gaming.service.repository.IRepository;
import org.gaming.service.repository.Repository;
import org.gaming.service.service.AbstractService;
import org.gaming.tool.DateTimeUtil;
import org.gaming.tool.LocalDateTimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.t2.game.server.foundation.starting.ApplicationSettings;
import org.t2.game.server.module.backstage.BackstagePoster;
import org.t2.game.server.module.player.model.Player;

import sh.t2.share.apiutil.GameApi;
import sh.t2.share.module.player.form.PlayerTable;
import sh.t2.share.module.player.form.PlayerTable.PlayerData;

/**
 * @author YY
 */
@Service
public class PlayerService extends AbstractService<Player> implements Lifecycle {
	
	@Autowired
	private ApplicationSettings applicationSettings;
	@Autowired
	private BackstagePoster backstagePoster;
	
	//<后台用户ID_服务器ID，玩家ID>
	private ConcurrentMap<String, Long> openIdToPlayerId = new ConcurrentHashMap<>();
	//上报数据的队列
	private Queue<Player> reportQueue = new ConcurrentLinkedQueue<>();
	//名字缓存
	private ConcurrentMap<String, Long> names = new ConcurrentHashMap<>();
	
	
	public Player getPlayerByOpenIdAndServerId(String openId, int serverId) {
		Long playerId = openIdToPlayerId.get(openId + "_" + serverId);
		if(playerId == null) {
			return null;
		}
		return this.repository().getByKeys(playerId);
	}
	
	public Player getEntity(long playerId) {
		return this.repository().getByKeys(playerId);
	}
	
	@Override
	public void start() throws Exception {
		for(Player player : this.repository().getAll()) {
			openIdToPlayerId.put(player.getOpenId() + "_" + player.getServerId(), player.getId());
			names.put(player.getNick(), player.getId());
		}
	}
	
	@Override
	public void mergeServer(int mergeDbZoneId) {
		IRepository<Player> repository = Repository.get(mergeDbZoneId, Player.class);
		List<Player> mergeDatas = repository.getBaseDao().queryAll();
		this.repository().insertAll(mergeDatas);
	}

	@Override
	public void insert(Player t) {
		super.insert(t);
		openIdToPlayerId.put(t.getOpenId() + "_" + t.getServerId(), t.getId());
		names.put(t.getNick(), t.getId());
	}
	
	public void addToReport(Player player) {
		if (this.reportQueue.contains(player)) {
			return;
		}
		this.reportQueue.add(player);
	}

	/**
	 * 向后台上报玩家数据
	 */
	@LoopingTask(name = "PlayerTimer-后台数据上报", spaceTime = DateTimeUtil.ONE_SECOND_MILLIS * 30, execGroup = 1)
	private void reportToBackstage() {
		if (reportQueue.isEmpty()) {
			return;
		}
		Player player = reportQueue.poll();
		PlayerTable playerTable = new PlayerTable();
		playerTable.setServerId(applicationSettings.getGameServerId());

		while (player != null) {
			PlayerData data = new PlayerData();
			data.setPlayerId(player.getId());
			data.setPlatformId(player.getPlatformId());
			data.setChannelId(player.getChannelId());
			data.setServerId(player.getServerId());
			data.setOpenId(player.getOpenId());
			data.setNick(player.getNick());
			data.setLevel((int)player.getLevel());
			data.setVipLevel(player.getVipLevel());
			data.setRecharge(player.getRecharge());
			data.setOnline(player.isOnline());
			data.setBornTime(LocalDateTimeUtil.toEpochMilli(player.getInsertTime()));
			data.setLastLoginTime(player.getLastLoginTime());
			data.setLastLogoutTime(player.getLastLogoutTime());
			data.setForbidEndTime(player.getForbidEndTime());
			data.setForbidRankTime(player.getForbidRankTime());
			data.setLoginIp(player.getLoginIp());
			data.setDeviceModel(player.getDeviceModel());
			playerTable.getDatas().add(data);
			player = reportQueue.poll();
		}
		backstagePoster.jsonPost(GameApi.playerReport, playerTable);
		logger.info("向后台上报玩家数量{}", playerTable.getDatas().size());
	}
	
	@Override
	public void stop() throws Exception {
		reportToBackstage();
	}
	
	public boolean hasSameNick(String nick) {
		return names.containsKey(nick);
	}
	
	public void changeNick(Player player, String oldNick) {
		names.remove(oldNick);
		names.put(player.getNick(), player.getId());
	}
	
	public boolean isWhite(long channelId, String openId) {
		Map<String, Object> map = new HashMap<>();
		map.put("channelId", channelId);
		map.put("openId", openId);
		String response = backstagePoster.formPost(GameApi.isWhiteList, map);
		if (response == null) {
			return false;
		}
		return "true".equals(response);
	}
	
	public boolean isForbidIp(String ip) {
		Map<String, Object> map = new HashMap<>();
		map.put("ip", ip);
		String response = backstagePoster.formPost(GameApi.isForbidIp, map);
		if (response == null) {
			return false;
		}
		return "true".equals(response);
	}
	
	public int getPlayerNum() {
		return this.repository().getSize();
	}
}
